﻿@model DJY.Domain._02_ViewModel.WorkFlowInstance
@using Newtonsoft.Json;
@using DJY.Code.Helper
@using DJY.Domain._02_ViewModel
@using DJY.Domain._05_Enum
@{
    ViewBag.Title = "Form";
    Layout = "~/Views/Shared/_Form.cshtml";
}
<style>
    .flow-title{
        text-align:center;
        font-weight:bold;
        font-size:25px;
    }
    .row{
        margin-bottom:4px;
    }
    .flow-name{
        text-align: center;
        height:28px;
        line-height:28px;
    }
    .flow-model-key.required .flow-name:after,.flow-name.required:after{
        color: red;
        content: "\0020*";
    }

    .flow-key .form-control {
        padding: 3px;
        line-height: unset;
        height: 28px;
    }

    .flow-nodes {
        max-height: 200px;
    }

    .flow-node-list {
        list-style: none;
    }

    li.flow-node.current {
        color: red;
        font-weight: bold;
    }

    legend{
        margin-bottom:5px;
        font-size:15px;
        text-indent:5px;
    }

    ul{
        padding-left:10px;
    }
</style>
<link href="~/Content/css/timeline.css" rel="stylesheet" />
<script>
    var flow = @Html.Raw(JsonConvert.SerializeObject(Model, WorkFlowHelper.IgnoreNullSettings)),
        taskType = @((int)WFNodeType.Task), auditType = @((int)WFNodeType.Audit),
        taskKey = "@WorkFlowHelper.NODE_RESULT_KEY",auditKey = "@WorkFlowHelper.NODE_AUDIT_KEY",
        auditRemarkKey = "@WorkFlowHelper.NODE_AUDIT_REMARK";

    function setReadonly(p, b) {
        if (b) {
            p.addClass("readonly").find("input,textarea").prop("readonly", true);
            p.find("select,:checkbox,:radio,:file,input.flow-action,input.input-wdatepicker").prop("disabled", true);
            p.addClass("disabled").find(".flow-list-actions,.flow-action").remove();
        }
        else {
            p.removeClass("readonly").find("input,textarea").prop("readonly", false).prop("disabled", false);
            p.find("select,:checkbox,:radio,:file,input.flow-action,input.input-wdatepicker").prop("readonly", false).prop("disabled", false);
            p.removeClass("disabled").find(".flow-action").removeClass("disabled");
        }
    }

    function setListState(mk, s) {
        if (!s.show) {
            mk.hide();
        }
        else {
            mk.show();
            if (s.readOnly) {
                mk.addClass("readonly").addClass("disabled").children(".flow-list-actions,.flow-action").remove();
                mk.children("tfoot,thead").each(function (i,o) {
                    setReadonly($(o), true);
                });
            }
            else {
                mk.removeClass("readonly").removeClass("disabled");
                mk.children("tfoot,thead").each(function (i,o) {
                    setReadonly($(o), false);
                });
            }

            if (s.required) {
                mk.addClass("required");
            }
            else {
                mk.removeClass("required");
            }
        }
    }

    //初始化流程，处理页面显示和隐藏
    function initFlow() {
        if (flow.error || window.flowHasInit) {
            return;
        }

        //非任务类型，只读
        if ((flow.node.type & taskType) != taskType) {
            //只读
            setReadonly($(".flow-form"),true);
        }
        else if (flow.modelKeys) {
            //按配置设置
            for (var k in flow.modelKeys) {
                var v = flow.modelKeys[k];
                var mk = $(".flow-form").find(".flow-key[data-key='" + k + "']");
                if (mk.length == 0) {
                    mk = $(".flow-form").find(".flow-action[data-key='" + k + "']");
                    if (mk.length > 0) {
                        if (v.show) {
                            mk.show();
                        }
                        else {
                            mk.remove();
                        }
                        continue;
                    }

                    mk = $(".flow-form").find(".flow-list[data-key='" + k + "']");
                    if (mk.length > 0) {
                        setListState(mk, v);
                        continue;
                    }
                        
                    if (k.indexOf("-") == -1) {
                        continue;
                    }

                    mk = $(".flow-form").find(".flow-column[data-key='" + k + "']");
                    if (mk.length == 0) {
                        continue;
                    }
                }

                if (!v.show) {
                    mk.closest(".flow-model-key").hide();
                }
                else {
                    mk.closest(".flow-model-key").show();
                    setReadonly(mk, v.readOnly);
                    if (v.required) {
                        mk.addClass("required").prev(".flow-name").addClass("required");
                        mk.closest(".flow-model-key").addClass("required");
                    }
                    else {
                        mk.removeClass("required").prev(".flow-name").removeClass("required");
                        mk.closest(".flow-model-key").removeClass("required");
                    }
                }
            }
        }
    }

    function _getInputValue(o) {
        if (o.is(":checkbox") || o.is(":radio")) {
            var ck = o.prop("checked");
            var y = o.val() || o.data("yes"), n = o.data("no");
            if (ck && y) {
                ck = y;
            }
            else if (!ck && n) {
                ck = n;
            }

            return ck;
        }
        else {
            return o.val();
        }
    }

    function getDataType(t) {
        return (t === null || t === "" || t === undefined || t == "1") ? 1 : 0;
    }

    function _getFlowKeyProp(mk, k,cb) {
        var ps = [];
        if (!mk || !k) {
            return ps;
        }

        var type = getDataType(mk.data("type"));
        var name = null;
        var fname = mk.prev(".flow-name");
        if (fname.length > 0) {
            name = fname.text().trim();
        }
        
        var txt = mk.find("input,textarea,select");
        if (txt.length == 0) {
            if (mk.hasClass("flow-action"))
                return;
            var p = { key: k, value: mk.data("value"), name: name || mk.data("name"), type: type };
            ps.push(p);
            if (cb) {
                cb(p);
            }
        }
        else if (txt.length == 1) {
            if (txt.attr("data-ignore")) {
                return;
            }
            var p = { key: k, value: _getInputValue(txt), name: name || mk.data("name"), type: type };
            ps.push(p);
            if (cb) {
                cb(p);
            }
        }
        else {
            var mutil = {}, isMulti = mk.data("multi"), isSingle = mk.data("single");
            txt.each(function (i, o) {
                var key = $(o).data("key");
                if (!key) return;

                if (isMulti && $(o).is(":checkbox")) {
                    if ($(o).is(":checked")) {
                        //复选多个
                        var v = $(o).val() || $(o).data("yes");
                        if (v) {
                            if (!mutil[key]) {
                                mutil[key] = { key: key, value: v, name: $(o).data("name") || name, type: getDataType($(o).data("type"))};
                            }
                            else if (mutil[key].value) {
                                mutil[key].value += "," + v;
                            }
                        }
                    }
                }
                else if (isSingle && $(o).is(":radio")) {
                    if ($(o).is(":checked")) {
                        //单选多个
                        var v = $(o).val() || $(o).data("yes");
                        if (v) {
                            if (!mutil[key]) {
                                mutil[key] = { key: key, value: v, name: $(o).data("name") || name, type: getDataType($(o).data("type")) };
                            }
                            else {
                                mutil[key].value = v;
                            }
                        }
                    }
                }
                else {
                    mutil[key] = { key: key, value: _getInputValue($(o)), name: $(o).data("name") || name, type:getDataType($(o).data("type"))};
                }
            });

            for (var k in mutil) {
                if (cb) {
                    cb(mutil[k]);
                }

                ps.push(mutil[k]);
            }
        }
        return ps;
    }

    function _getModelKeyName(mk) {
        var name = mk.data("name");
        if (!name) {
            var fname = mk.prev(".flow-name");
            if (fname.length > 0) {
                name = fname.text();
            }
            else if (mk.hasClass("flow-column")) {
                var idx = mk.closest("tr").index();
                if (idx > -1) {
                    var c = mk.closest(".flow-list");
                    name = c.data("name");
                    c = c.children("thead").children("tr").children(":eq(" + idx + ")");
                    if (c.length > 0) {
                        name += c.text();
                    }
                }
            }
        }
        return name;
    }

    function _isValidValue(v) {
        return v || v === false;
    }

    function _getFlowList(mk,pname) {
        var list = [];
        mk.find("tbody").children(".flow-row").each(function (i,r) {
            var row = {};
            $(r).children(".flow-model-key").each(function (i,c) {
                $(c).children(".flow-column").each(function (i,cc) {
                    var k = $(cc).data("key");
                    if (k && k.indexOf(pname) == 0) {
                        if ($(cc).hasClass(".flow-list")) {
                            var cname = k.substr(pname.length + 1);
                            if (!cname) {
                                return;
                            }
                            row[cname] = _getFlowList($(cc),k);
                            if ($(cc).hasClass("required") && (!row[cname] || row[cname].length == 0)) {
                                var name = _getModelKeyName($(cc));
                                throw new Error(name ? (name + "必填") : "必填项(" + k + ")不能为空");
                            }
                        }
                        else {
                            _getFlowKeyProp($(cc), k, function (p) {
                                var cname = p.key.substr(pname.length + 1);
                                if (!cname) {
                                    return;
                                }

                                if ($(cc).hasClass("required")) {
                                    if (!_isValidValue(p.value)) {
                                        p.value = row[cname];
                                        if (!_isValidValue(p.value)) {
                                            var name = _getModelKeyName($(cc));
                                            throw new Error(name ? (name + "必填") : "必填项(" + k + ")不能为空");
                                        }
                                    }
                                }
                                row[cname] = p.value;
                            });
                        }
                    }
                });
            });
            list.push(row);
        });
        return list;
    }

    function beforeProcess() {
        var data = {}, flag = true;
        data.flowId = $("#flowId").val();
        data.flowNodeId = $("#flowNodeId").val();
        data.nodeId = $("#nodeId").val();
        data.props = [];
        if ((flow.node.type & auditType) == auditType) {
            var auditResult = null, auditRemark = null;
            var mk = $(".flow-key[data-key='" + auditKey + "']");
            if (mk.length > 0) {
                _getFlowKeyProp(mk, auditKey, function (p) {
                    if (p.key == auditKey) {
                        auditResult = p.value;
                    }
                    data.props.push(p);
                });
            }

            mk = $(".flow-key[data-key='" + auditRemarkKey + "']");
            if (mk.length > 0) {
                _getFlowKeyProp(mk, auditRemarkKey, function (p) {
                    if (p.key == auditRemarkKey) {
                        auditRemark = p.value;
                    }
                    data.props.push(p);
                });
            }

            if (!auditResult) {
                $.modalAlert("请选择审批结果", "error");
                return false;
            }

            if (auditResult == "0" && !auditRemark) {
                $.modalAlert("请输入审批说明", "error");
                return false;
            }
        }

        if ((flow.node.type & taskType) == taskType && $(".flow-form").length > 0) {
            $(".flow-form").find(".flow-key[data-key]").each(function (i, o) {
                var k = $(o).data("key");
                if (!k) {
                    return;
                }
                _getFlowKeyProp($(o), k, function (p) {
                    if (flag && $(o).hasClass("required") && !_isValidValue(p.value)) {
                        flag = false;
                        $.modalAlert(p.name ? (p.name + "必填") : "必填项(" + p.key + ")不能为空", "error");
                        return;
                    }
                    data.props.push(p);
                });

                if (!flag) {
                    return false;
                }
            });

            if (!flag) {
                return false;
            }

            $(".flow-form").children(".flow-list[data-key]").each(function (i, o) {
                var mk = $(o),k = $(o).data("key");
                if (!k) {
                    return;
                }

                var p = { key: k, type: mk.data("type") || "1" };
                var fname = mk.prev(".flow-name");
                if (fname.length > 0) {
                    p.name = fname.text().trim();
                }
                if (!p.name) {
                    p.name = mk.data("name");
                }

                try {
                    p.value = _getFlowList(mk, k);
                    if ($(o).hasClass("required") && (!p.value || p.value.length == 0)) {
                        $.modalAlert(p.name ? (p.name + "必填") : "必填项(" + k + ")不能为空", "error");
                        flag = false;
                        return false;
                    }
                        p.value = JSON.stringify(p.value);
                    data.props.push(p);
                }
                catch (err) {
                    $.modalAlert(err.message, "error");
                    flag = false;
                    return false;
                }
            });
        }

        return flag ? data : null;
    }
</script>
<form id="form1">
    @if (!string.IsNullOrEmpty(Model.error))
    {
        <div class="alert alert-danger flow-error">@Model.error</div>
    }
    else
    {
        @Html.Hidden("flowId", Model.id, new { id = "flowId" });
        @Html.Hidden("flowNodeId", Model.flowNodeId, new { id = "flowNodeId" });
        @Html.Hidden("nodeId", Model.node.id, new { id = "nodeId" });
        <div class="flow-title @(Model.dev ? "blue":"")">@Model.name</div>
        if (!string.IsNullOrEmpty(Model.node.businessUrl))
        {
            <div class="flow-form">
                @{
                    Html.RenderPartial(Model.node.businessUrl, (object)Model);
                }
            </div>
        }
        if (Model.node.type != (int)WFNodeType.Start && !string.IsNullOrEmpty(Model.node.auditUrl)
                        && (Model.node.type & (int)WFNodeType.Audit) == (int)WFNodeType.Audit)
        {
            Html.RenderPartial(Model.node.auditUrl, (object)Model);
        }

        if (Model.nodes != null && Model.nodes.Count > 0)
        {
    <fieldset>
        <legend>流转</legend>
        <section class="timeline">
            @foreach (WorkFlowInstanceNode node in Model.nodes)
            {
                <div class="timeline-item">
                    <div class="timeline-img location">
                        <img src="/Content/img/cd-icon-location.svg">
                    </div>
                    <div class="timeline-content">
                        @if (node.nodeType == (int)WFNodeType.Start && string.IsNullOrEmpty(node.fromNode))
                        {
                            <span class="operator">@Model.createUserName</span>
                            <span class="date">@Model.createTime</span>
                            <span class="action">发起流程</span>
                        }
                        else
                        {
                            <span class="operator">@node.createUser</span>
                            <span class="date">@node.createTime</span>
                            <span class="action">@node.remark</span>
                        }
                    </div>
                </div>
            }
        </section>
    </fieldset>
        }
    }
</form>
<script>
    function _processResult(rsp) {
        if (rsp.state) {
            $.modalAlert("操作成功", "success");
        }
        else {
            if (!rsp.msg) {
                rsp.msg = "操作失败";
            }
            $.modalAlert(rsp.msg, "error");
        }
    }

    //处理回调
    function process(cb) {
        //有错误，直接关闭窗口
        if (flow.error || !flow.node.id) {
            if (cb) {
                cb({ state: false });
            }
            return;
        }

        var data = {};
        if (window.beforeProcess) {
            data = window.beforeProcess();
            if (!data) {
                return;
            }
        }

        if (flow.dev) {
            $.modalAlert(JSON.stringify(data), "warning");
            return;
        }

        $.loading(true);
        $.ajax({
            url: "/WorkFlow/WorkFlow/ProcessFlow",
            headers: { "__RequestVerificationToken": $('[name=__RequestVerificationToken]').val() },
            contentType: "application/json",
            data: JSON.stringify(data),
            type: "post",
            dataType: "json",
            success: function (rsp) {
                $.loading(false);
                if (cb) {
                    cb(rsp);
                }
                else {
                    _processResult(rsp);
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                $.loading(false);
                $.modalMsg(errorThrown, "error");
            }
        });
    }

    $(function () {
        initFlow();
    });
</script>
